<template>
    <el-row>
        <el-col :span="4" class="scrollDiv" style="height:calc(100vh - 90px);overflow-y: scroll">
        <TankRoom @selectRoom = selectRoom />
        </el-col>
        <el-col v-show="room.id !== 0" :span="20" style="display: flex;flex-flow:column;justify-content: flex-start;align-items: center" >
            <div style="height:50px;display: flex;justify-content: space-between;align-items: center">
                <el-form inline >
                <el-form-item>
                    {{room.name}}
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" plain  @click="startGame">开始游戏</el-button>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" plain  @click="stopGame">结束游戏</el-button>
                </el-form-item>
                </el-form>
            </div>
            <div class="tankArea" tabindex="0" ref="tankArea"
                 @keydown.right="startMoveRight"
                 @keyup.right="stopMove"

                 @keydown.left="startMoveLeft"
                 @keyup.left="stopMove"

                 @keydown.up="startMoveUp"
                 @keyup.up="stopMove"

                 @keydown.down="startMoveDown"
                 @keyup.down="stopMove"

                 @keydown.space="shoot"
                 :style = tankAreaStyle>
                <!--<div v-for="tank in tanks" :class="tank.class" :style = "'top:' + tank.top + 'rem; left:' + tank.left + 'rem'">-->
                <!--</div>-->
                <div v-for="(tank, index) in tankMap" :key="index" :class="tank[1].campClass+tank[1].direcClass" :style = "'top:' + tank[1].top + 'rem; left:' + tank[1].left + 'rem'">
                    <div style="position: absolute;font-size:10px;bottom:-10px;right:-10px">{{tank[1].camp}}</div>
                </div>
                <!--<div v-for="cloud in clouds" class="cloud" :style = "'top:' + cloud.top + 'rem; left:' + cloud.left + 'rem'" ></div>-->
                <div v-for="(bullet, index) in bulletMap" :key="index" :class="bullet[1].class" :style = "'top:' + bullet[1].top + 'rem; left:' + bullet[1].left + 'rem'">
                </div>
                <Explosion v-for="explosion in explosions" @removeExplosion="removeExplosion"
                           :style = "'top:' + explosion.top + 'rem; left:' + explosion.left + 'rem'" :id="explosion.id">
                </Explosion>
            </div>
        </el-col>
    </el-row>
    <audio style="display: none" src='/tank/audio/explode.wav' ref="explode" preload="auto"></audio>
    <audio style="display: none" src='/tank/audio/tank_fire.wav' ref="tankFire" preload="auto"></audio>
    <audio style="display: none" src='/tank/audio/tank_move.wav' ref="tankMove" loop  preload="auto"></audio>
    <audio style="display: none" src='/tank/audio/startGame.mp3' ref="startAudio"  preload="auto"></audio>
</template>

<script setup>

    import Explosion from '@/components/recreation/tank/Explosion.vue'
    import TankRoom from '@/components/recreation/tank/TankRoom.vue'
    import request from '@/utils/request.js'
    import Tank from './tank.js'
    import { ElMessage } from 'element-plus'
    import {ref, reactive, onMounted,nextTick,computed,onUnmounted} from 'vue'
    let explode = ref(null)
    let tankFire = ref(null)
    let tankMove = ref(null)
    let startAudio = ref(null)

    let ENEMY = 'enemy'
    let OUR = 'our'
    let tankMap = reactive(new Map());
    let bulletMap = reactive(new Map());

    let bullets = reactive([]);
    let explosions = reactive([]);
    let clouds = reactive([]);
    let tankSize = 4

    let maxHeight = ref(35)
    let maxWidth = ref(55)

    let MYTANK = "tank"
    let BADTANK = "tankBad"
    let armynum = ref(1)
    let tankArea = ref(null)

    let tankSpeed = 0.8
    let bulletSpeed = 1.5
    let bulletsInterval = null
    let tanksInterval = null
    let tankAreaStyle = computed(()=>{
        return "width:" + maxWidth.value +"rem;height:" + maxHeight.value + "rem"
    })
    let userdb = null
    let websocket = null
    let room = reactive({id:0})
    let connect = false
    onUnmounted(() => {
        if(connect){
            websocket.close()
        }
    })

    function initBulletsInterval(){
        if(bulletsInterval){
            return
        }
         bulletsInterval = setInterval(function () {
             for (let [key, bullet] of bulletMap) {

                 let direction = bullet.direction
                 let hitTank = false
                 if(direction == 'left'){
                     bullet.left =  bullet.left - bulletSpeed
                     hitTank = isHitTank(bullet)
                     if(bullet.left <= -0.75 || hitTank){
                         bulletMap.delete(bullet.id)
                     }
                 }else if(direction == 'right'){
                     bullet.left =  bullet.left + bulletSpeed
                     hitTank = isHitTank(bullet)
                     if(bullet.left >= maxWidth.value || hitTank){
                         bulletMap.delete(bullet.id)
                     }
                 }else if(direction == 'up'){
                     bullet.top = bullet.top - bulletSpeed
                     hitTank = isHitTank(bullet)
                     if(bullet.top <= -0.75 || hitTank){
                         bulletMap.delete(bullet.id)
                     }
                 }else if(direction == 'down'){
                     bullet.top = bullet.top + bulletSpeed
                     hitTank = isHitTank(bullet)
                     if(bullet.top >= maxHeight.value || hitTank){
                         bulletMap.delete(bullet.id)
                     }
                 }
                 if(bullet.camp == userdb.nickName && !hitTank){
                     websocket.send(JSON.stringify({type: "bullet", id:bullet.id, direction:bullet.direction, camp: userdb.nickName, top: bullet.top, left: bullet.left,class:bullet.class}))
                 }
             }
        },50)
    }

    function initTanksInterval(){
        if(tanksInterval){
            return
        }
        tanksInterval = setInterval(function () {

            for (let [key, tank] of tankMap) {
                if(tank.moving){
                    if(tank.direction === 'right'){
                        if(tank.left >= maxWidth.value - tankSize){
                            tank.left = maxWidth.value - tankSize
                        }else {
                            tank.left = tank.left + tankSpeed
                        }
                    }else if(tank.direction === 'up'){
                        if(tank.top <= 0){
                            tank.top = 0
                        }else {
                            tank.top = tank.top - tankSpeed
                        }
                    }else if( tank.direction === 'left'){
                        if(tank.left <= 0){
                            tank.left = 0
                        }else{
                            tank.left = tank.left - tankSpeed
                        }
                    }else if( tank.direction === 'down'){
                        if(tank.top >= maxHeight.value - tankSize){
                            tank.top = maxHeight.value - tankSize
                        }else{
                            tank.top = tank.top + tankSpeed
                        }
                    }
                    if(tank.camp === userdb.nickName){
                        websocket.send(JSON.stringify({type:"tank", camp:userdb.nickName,campClass: tank.campClass, direcClass: tank.direcClass, top:tank.top, left:tank.left}))
                    }
                }
            }
        },50)
    }

    function isHitTank(bullet){
        for (let [key, tank] of tankMap) {
            if(tank.camp === bullet.camp){
                continue
            }
            if((bullet.top > tank.top) && (bullet.left >tank.left) && (bullet.top < tank.top + tankSize) && (bullet.left < tank.left + tankSize)){
                tankMap.delete(key)
                if(tank.camp === userdb.nickName){
                    ElMessage.error("游戏失败")
                }
                explode.value.play()
                let num = new Date().getTime()
                explosions.push({top:tank.top, left:tank.left, id:num})
                websocket.send(JSON.stringify({type:"explosion", top:tank.top, left:tank.left, id:num, bulletId:bullet.id, tankName:tank.camp }))
                return true
            }
        }
    }

    function shoot(){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        let bullet = tank.shoot()
        bulletMap.set(bullet.id, bullet)
    }

    function startMoveRight(){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        tank.startMoveRight()
    }

    function startMoveLeft(){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        tank.startMoveLeft()
    }

    function startMoveUp(){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        tank.startMoveUp()
    }

    function startMoveDown(i){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        tank.startMoveDown()
    }

    function stopMove(){
        let tank = tankMap.get(userdb.nickName)
        if(!tank){return}
        tank.stopMove()
    }

    function removeExplosion(id){

        for (let i = explosions.length - 1; i >=0 ; i--) {
            let explosion = explosions[i]
            if(explosion.id === id){
                explosions.splice(i,1)
                break
            }
        }
    }

    function selectRoom(row) {
        if (row.id !== room.id && !connect){
            room.id = row.id
            room.name = row.name
        } else{
            ElMessage.error("已经选择房间")
        }
    }

    function startGame(){
        if(room.id === 0 ){
            ElMessage.error("请先选择房间")
            return
        }
        if(connect){
            websocket.close()
        }
        userdb = JSON.parse(sessionStorage.getItem("user")||"{}")
        let host = window.location.host
        websocket  = new WebSocket(`ws://${host}/socket/tankOnline/` + room.id + "/" + userdb.id)

        websocket.onerror = function (e) {
            ElMessage({message: "websocket连接出错", type: 'error'})
        }
        websocket.onclose = function(e){
            console.log(e)
        }
        websocket.onopen = function(){
            connect = true
            let top = Math.round((maxHeight.value - tankSize) * Math.random())
            let left = Math.round((maxWidth.value - tankSize) * Math.random())
            let tank = new Tank(top, left, MYTANK, tankMove, tankFire, userdb.nickName)
            tankMap.set(userdb.nickName, tank);
            websocket.send(JSON.stringify({type:"tank", camp:userdb.nickName,campClass: tank.campClass, direcClass: tank.direcClass, top: tank.top, left: tank.left}))
        }

        websocket.onmessage = function (event) {
            let payload = JSON.parse(event.data);
            if(payload.type === 'tank'){
                if(!payload.close){
                    payload.campClass = BADTANK
                    let tank = tankMap.set(payload.camp, payload)
                }else{
                    tankMap.delete(payload.camp)
                }
            }else if(payload.type === 'bullet'){

                bulletMap.set(payload.id, payload)

            }else if(payload.type === 'explosion'){
                tankMap.delete(payload.tankName)
                bulletMap.delete(payload.bulletId)
                explosions.push({top:payload.top, left:payload.left, id:payload.id})
            }else if(payload.type === 'msg'){
                ElMessage.error(payload.content)
                tankMap.dates(userdb.nickName);
            }
        }

        initTanksInterval()
        initBulletsInterval()

        tankArea.value.focus()
    }

    function stopGame(){
        if(websocket && websocket.readyState === 1){
            let tank = tankMap.get(userdb.nickName)
            if(tank){
                websocket.send(JSON.stringify({type:"tank",close:true, camp:userdb.nickName,campClass: tank.campClass, direcClass: tank.direcClass, top:tank.top, left:tank.left}))
            }
            websocket.close()
        }
        connect = false
        clouds.splice(0, clouds.length)
        clearInterval(tanksInterval)
        tanksInterval = null

        clearInterval(bulletsInterval)
        bulletsInterval = null

        for (let [key, bullet] of bulletMap) {
            bulletMap.delete(key)
        }
        for (let [key, tank] of tankMap) {
            tankMap.delete(key)
        }
        room.id = 0
    }

</script>
<style lang="css" scoped>
    .address {overflow:hidden;white-space:nowrap;word-wrap:break-word;text-overflow:"ellipsis";}
    .head {background-color: #9561cc}
    [v-cloak]{
        display: none  !important;
    }
    .demo-form-inline{
        display: flex !important;
        justify-content: flex-start !important;
        align-items: center !important;
    }
    .tank{
        position:absolute;
        width: 4rem;
        height: 4rem;
        background-image: url('../../assets/tank/GoodTank1.png');
        background-size: cover
    }
    .cloud{
        position:absolute;
        width: 4rem;
        height: 4rem;
        background-color: #ccc;
        z-index: 10;
    }
    .tankBad{
        position:absolute;
        width: 4rem;
        height: 4rem;
        background-image: url('../../assets/tank/tank_.png');
        background-size:cover;
    }
    .bulletRight{
        position:absolute;
        width: 1.5rem;
        height: .5rem;
        background-image: url('../../assets/tank/bulletR.png');
        background-size: cover
    }
    .bulletLeft{
        position:absolute;
        width: 1.5rem;
        height: .5rem;
        background-image: url('../../assets/tank/bulletL.png');
        background-size: cover
    }
    .bulletUp{
        position:absolute;
        width: .5rem;
        height: 1.5rem;
        background-image: url('../../assets/tank/bulletU.png');
        background-size: cover
    }
    .bulletDown{
        position:absolute;
        width: .5rem;
        height: 1.5rem;
        background-image: url('../../assets/tank/bulletD.png');
        background-size: cover
    }

    .turnDown{
        transform : rotate(180deg)
    }

    .turnUp{
        transform : rotate(0deg)
    }

    .turnLeft{
        transform : rotate(270deg)
    }

    .turnRight{
        transform : rotate(90deg)
    }

    .tankArea{
        background-color: #cbdcff;
        overflow: hidden;
        border-radius: 5px;
        position: relative;
        outline-offset: -1px;
    }

    .tankArea:focus{
        outline: none;
        box-shadow: 0 0 0 1px #7081ff, 0 0 0 2px white, 0 0 0 3px #7081ff;
    }
    </style>